#!/usr/bin/python
# -*- coding: UTF-8 -*-
import json

import requests
from bs4 import BeautifulSoup

from enums.sys_type_enum import SysTypeEnum
from utils.commit.oversea_regions import OVERSEA_REGIONS
from utils.commit.submit_tx import SubmitTypeEnum
from utils.commit.submit_wjx_v2 import QuestionareSpider
from utils.common.init_app import app
from utils.common.time_util import get_time_stamp13_now, timestamp_to_formated_str, get_time_str_before_now_s
from utils.common.uuid_util import uuid4
from utils.ip_proxy.pinzan_ip_proxy import PinzanHttpProxy
from utils.submit_ua import UserAgentGenerate

session = requests.Session()


class QuestionareSpiderWjw(QuestionareSpider):
    def __init__(self, send_title_link, pz_obj, wo_topic_id, sleep_time, area):
        self.sessions = session
        # self.proxy_obj = proxy_obj
        self.pz_obj: PinzanHttpProxy = pz_obj
        self.title_link = send_title_link
        self.wo_topic_id = wo_topic_id
        self.headers = {}
        self.sleep_time = sleep_time or 20  # 问卷需要填写的时间,默认20秒
        self.area = area
        self.ua = UserAgentGenerate.random_phone_micro_messenger()  # 初始化实例默认获取一个ua
        self.can_get_7_code = True

    def get_submit_result(self, submitdata, submit_type):
        """
        提交问卷
        :param submitdata: 需要提交数据
        :return:
        """
        # 1. 构建提交参数
        cur_header = dict()
        cur_header['user-agent'] = self.ua  # 模拟微信请求头
        # app.logger.debug(f'cur_header={cur_header}')
        tmp_arr = self.title_link.split('www.wenjuan.com')
        url = tmp_arr[0] + 'www.wenjuan.com/api/rspd' + tmp_arr[1]
        # app.logger.debug(f'url={url}')
        # app.logger.debug(f'submitdata={submitdata}')
        # 2. 判断ip是否可用
        self.is_ip_available()  # 判断当前ip是否过期，如果过期重新获取一个ip并且立即发送请求
        # 3. 发送请求
        # app.logger.debug(f'area：{self.area}')
        if self.area in OVERSEA_REGIONS:  # 海外发送请求
            # app.logger.debug('发送到海外服务器')
            # 1, 获取海外的代理地址，2，发送到海外服务器
            upper_area = self.area.upper()
            p_url = 'http://cuveecui-' + upper_area + ':yydj8888@proxy.smartproxycn.com:1000'
            oversea_param_dict = dict()
            oversea_param_dict['submit_data'] = json.dumps(submitdata)
            oversea_param_dict['request_headers'] = cur_header
            oversea_param_dict['proxy_url'] = p_url
            oversea_send_url = url
            encoded_url = oversea_send_url
            oversea_param_dict['url'] = encoded_url
            # oversea_param_dict['submit_data'] = json.dumps(submitdata)
            # app.logger.debug('打印请求参数：')
            # app.logger.debug(oversea_param_dict)
            sys_oversea_url = 'http://8.137.54.97:7002/api/overseas/submit'
            oversea_header = dict()
            res = requests.post(url=sys_oversea_url, headers=oversea_header, json=oversea_param_dict, timeout=10)
            oversea_response = res.json()
            if oversea_response and 200 == oversea_response.get('code'):
                pd = oversea_response.get('result')
            else:
                pd = '发送海外数据失败'
        else:  # 默认国内直接发送
            res = requests.post(url=url, headers=cur_header, json=submitdata, timeout=10, proxies=self.pz_obj.proxies,
                                allow_redirects=False)
            pd = res.content.decode()
        app.logger.info(f'response_data={pd}')
        return pd

    def submit(self, submitdata):
        """
        提交问卷
        :param submitdata: 需要提交数据
        :return:
        """
        pd = self.get_submit_result(submitdata, SubmitTypeEnum.WX)  # 默认微信提交
        if pd.startswith('10〒'):
            pass
        elif pd.startswith('5〒'):  # 5〒很抱歉，必须微信登录才能填写！
            # 默认就是微信提交，说明此时不应该再用微信提交，则转为使用手机提交
            self.ua = UserAgentGenerate.random_pc()  # 获取pd的ua
            pd = self.get_submit_result(submitdata, SubmitTypeEnum.PHONE)
        elif pd.startswith('7〒'):  # 需要智能验证
            pass
        else:
            pass
        return pd


def get_version(src_url):
    # src_url = 'https://www.wenjuan.com/s/UZBZJvgHD7/'
    cur_header = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36'
    }
    response = requests.get(url=src_url, headers=cur_header, timeout=10, allow_redirects=False)
    soup = BeautifulSoup(response.content, 'html.parser')
    script_tags = soup.find_all('script')
    src_data_json_str = ''
    for i in script_tags:
        t = i.text.strip()
        if i and t.startswith('window.__INITIAL_STATE__'):
            t = t.replace('window.__INITIAL_STATE__', '')
            if t:
                t = t.strip()[1:]
                arr = t.split(';(function()')
                src_data_json_str = arr[0]
    if not src_data_json_str:
        app.logger.error('解析问卷失败，没有获取到题目内容')
    src_data_json = json.loads(src_data_json_str)
    version = src_data_json['version']
    return version


def convert_data_to_submit_data(db_title_arr, db_res_arr, title_link, sleep_time) -> str:
    """
    将数据库中的数据转换为需要提交的结果数据
    :param db_title_arr: 题目与数据库结果的映射关系数组
    :param db_res_arr: 需要提交的答案数组
    :param title_link: 问卷原始链接
    :param sleep_time: 睡眠时间（即一张问卷的总答题时长）
    :return:
    """
    tas = dict()
    for index in range(len(db_title_arr)):
        i = db_title_arr[index]
        indexes = i['data_index']
        cur_type = i['sys_type']
        qst_id = i['title_id']
        # page_id = i['page_id']
        options = i['options']
        if cur_type == SysTypeEnum.SINGLE.value:  # 单选题
            # 数据格式：｛"663c7d2b8c59b50add178467": ["663c7d2b8c59b50add178442"]}
            cur_value = str(db_res_arr[indexes[0]])
            if '-3' == cur_value:  # -3直接跳过这条数据
                continue
            opt_id_list = list()
            tas[qst_id] = opt_id_list
            for option in options:
                if str(option['value']) == cur_value:  # 所有数据转换为字符串进行比较
                    opt_id = option['rl_value']
                    opt_id_list.append(opt_id)
                    break  # 找到匹配的选项后跳出子循环
        elif cur_type == SysTypeEnum.MULTIPLE.value:  # 多选题
            # 数据格式：{"663c7d2b8c59b50add178468":[["663c7d2b8c59b50add178444"],["663c7d2b8c59b50add178446"]]}
            opt_id_list = list()
            tas[qst_id] = opt_id_list
            for option in options:
                db_value = str(db_res_arr[option['data_index']])
                if '-3' == db_value:  # -3直接跳过这条数据
                    break
                if '1' != db_value:
                    continue
                opt_id = option['rl_value']
                opt_id_list.append([opt_id])
            pass
        elif cur_type == SysTypeEnum.SINGLE_SELECT.value:  # 下拉单选题
            # 数据格式：{"663c7d2b8c59b50add178469":["663c7d2b8c59b50add178448"]}
            cur_value = str(db_res_arr[indexes[0]])
            if '-3' == cur_value:  # -3直接跳过这条数据
                continue
            opt_id_list = []
            tas[qst_id] = opt_id_list
            for option in options:
                if str(option['value']) == cur_value:  # 所有数据转换为字符串进行比较
                    opt_id = option['rl_value']
                    opt_id_list.append(opt_id)
                    break  # 找到匹配的选项后跳出子循环
        elif cur_type == SysTypeEnum.SCALE.value:  # 单选量表题
            # 数据格式：{"663c7d2b8c59b50add17846b":{"663c7d2b8c59b50add17844c":["5"]}}
            selected_value = str(db_res_arr[indexes[0]])
            if '-3' == selected_value:  # -3直接跳过这条数据
                continue
            opt_dict = dict()
            tas[qst_id] = opt_dict
            for option in options:
                if str(option['value']) == selected_value:  # 所有数据转换为字符串进行比较
                    opt_id = option['rl_value']
                    opt_dict[opt_id] = [selected_value]
                    break  # 找到匹配的选项后跳出子循环
        elif cur_type == SysTypeEnum.TEXT.value:  # 填空题
            # 数据格式：{"663c7d2b8c59b50add17846d":{"663c7d2b8c59b50add17844e_open":"填空内容"}}
            filled_value = db_res_arr[indexes[0]]
            if '-3' == filled_value:  # -3直接跳过这条数据
                continue
            opt_id = options[0]['rl_value'] + '_open'
            tas[qst_id] = {opt_id: filled_value}
        elif cur_type == SysTypeEnum.DATE.value:  # 日期题
            # 数据格式：{"663c7d2b8c59b50add17846c":{"663c7d2b8c59b50add17844d_open":"2024-01-25"}}
            filled_value = db_res_arr[indexes[0]]
            if '-3' == filled_value:  # -3直接跳过这条数据
                continue
            opt_id = options[0]['rl_value'] + '_open'
            tas[qst_id] = {opt_id: filled_value}
        elif cur_type == SysTypeEnum.MATRIX.value:  # 单选矩阵题
            # 数据格式：{"663c7d2b8c59b50add178470":{"663c7d2b8c59b50add178462":["663c7d2b8c59b50add178459"],"663c7d2b8c59b50add178463":["663c7d2b8c59b50add178459"]}}
            children = i['children']
            counter = 0
            row_id_dict = dict()
            tas[qst_id] = row_id_dict
            for cur_child in children:
                options = cur_child['options']
                cur_value = str(db_res_arr[indexes[counter]])
                if '-3' == cur_value:  # -3直接跳过这条数据
                    break
                row_id = cur_child['rl_value']
                opt_id_list = list()
                row_id_dict[row_id] = opt_id_list
                for option in options:
                    if str(option['value']) == cur_value:
                        opt_id = option['rl_value']
                        opt_id_list.append(opt_id)
                counter += 1
        elif cur_type == SysTypeEnum.CASCADE_DROPDOWN.value:  # 级联下拉题
            # 数据格式：
            db_value = db_res_arr[indexes[0]]
            if '-3' == db_value:  # -3直接跳过这条数据
                continue
            id_list = list()  # todo 待实现
        elif cur_type == SysTypeEnum.SLIDE.value or cur_type == SysTypeEnum.RATE.value:  # 滑动题或者比重题
            # 数据格式：{"663c7d2b8c59b50add178472":{"663c7d2b8c59b50add17845e":[83],"663c7d2b8c59b50add17845f":[17]}}
            opt_id_dict = dict()
            tas[qst_id] = opt_id_dict
            for option in options:
                db_value = db_res_arr[option['data_index']]
                if '-3' == db_value:  # -3直接跳过这条数据
                    break
                opt_id = option['rl_value']
                opt_id_dict[opt_id] = [db_value]
        elif cur_type == SysTypeEnum.SORTED.value:  # 排序题
            # 数据格式：{"663c7d2b8c59b50add17846a":{"663c7d2b8c59b50add178449":[2],"663c7d2b8c59b50add17844a":[1],"663c7d2b8c59b50add17844b":[3]}}
            opt_id_dict = dict()
            tas[qst_id] = opt_id_dict
            for option in options:
                db_value = db_res_arr[option['data_index']]
                if '-3' == db_value:  # -3直接跳过这条数据
                    is_jump = True
                    break
                opt_id = option['rl_value']
                sort_no = db_value
                if -2 == db_value:
                    sort_no = len(options)
                opt_id_dict[opt_id] = [sort_no]
        elif cur_type == SysTypeEnum.MULTIPLE_TEXT.value:  # 多项填空
            # 数据格式：{"663c7d2b8c59b50add17846e":{"663c7d2b8c59b50add17844f_open":"多填内容1","663c7d2b8c59b50add178450_open":"多填内容2","663c7d2b8c59b50add178451_open":"多填内容3"}}
            children = i['children']
            opt_id_dict = dict()
            tas[qst_id] = opt_id_dict
            for cur_child in children:
                db_value = db_res_arr[cur_child['data_index']]
                if '-3' == db_value:  # -3直接跳过这条数据
                    is_jump = True
                    break
                option_id = cur_child['rl_value']
                opt_id_dict[option_id + '_open'] = db_value
        elif cur_type == SysTypeEnum.MULTIPLE_MATRIX.value:  # 矩阵多选
            # 数据格式：{"663c7d2b8c59b50add178471":{"663c7d2b8c59b50add178464":[["663c7d2b8c59b50add17845a"],["663c7d2b8c59b50add17845c"]],"663c7d2b8c59b50add178465":[["663c7d2b8c59b50add17845c"]],"663c7d2b8c59b50add178466":[["663c7d2b8c59b50add17845a"],["663c7d2b8c59b50add17845c"]]}}
            children = i['children']
            counter = 0
            row_id_dict = dict()
            tas[qst_id] = row_id_dict
            for cur_child in children:
                options = cur_child['options']
                # cur_value = str(db_res_arr[indexes[counter]])
                # if '-3' == cur_value:  # -3直接跳过这条数据
                #     break
                row_id = cur_child['rl_value']
                opt_id_list = list()
                row_id_dict[row_id] = opt_id_list
                for option in options:
                    db_value = str(db_res_arr[option['data_index']])
                    if '-3' == db_value:  # -3直接跳过这条数据
                        break
                    if '1' != db_value:
                        continue
                    opt_id = option['rl_value']
                    opt_id_list.append([opt_id])
                counter += 1
        elif cur_type == SysTypeEnum.MATRIX_TEXT.value:  # 矩阵填空
            # 数据格式：{"663c7d2b8c59b50add17846f":{"663c7d2b8c59b50add178460":{"663c7d2b8c59b50add178452":"r1cl","663c7d2b8c59b50add178453":"r1c2","663c7d2b8c59b50add178454":"r1c3"},"663c7d2b8c59b50add178461":{"663c7d2b8c59b50add178452":"r2c1","663c7d2b8c59b50add178453":"r2c2","663c7d2b8c59b50add178454":"r2c3"}}}
            children = i['children']
            row_id_dict = dict()
            tas[qst_id] = row_id_dict
            for cur_child in children:
                cur_blank_list = list()
                options = cur_child['options']
                row_id = cur_child['rl_value']
                opt_id_dict = dict()
                row_id_dict[row_id] = opt_id_dict
                for option in options:
                    db_value = db_res_arr[option['data_index']]
                    if '-3' == db_value:  # -3直接跳过这条数据
                        break
                    opt_id = option['rl_value']
                    opt_id_dict[opt_id] = db_value
        pass
    app.logger.debug(f'tas={tas}')
    timestamp_now = get_time_stamp13_now()
    # timestamp转化为指定格式字符串
    submitdata = {
        "appkey": 'sqjDmXVd5LNYf9r4',
        "auto_submit_post": False,
        "finish_status": "1",
        "idy_uuid": str(uuid4()).replace('-', ''),
        "project_version": get_version(title_link),
        "question_captcha_map_str": "{}",
        "question_ids_skipped_by_time": "{}",
        "signature": str(uuid4()).replace('-', ''),
        "timestamp": timestamp_now,
        "timestr": get_time_str_before_now_s(sleep_time),
        "total_answers_str": json.dumps(tas),
        "web_site": "wenjuan_web",
        "wx_user_info_str": "{}"
    }
    sd = json.dumps(submitdata)
    app.logger.debug(f'submitdata={sd}')
    return submitdata


def do_submit(proxy_region: str, send_title_link: str, submitdata: str, sleep_time: int, wo_topic_id):
    # app.logger.debug(f'do_submit提交数据，wo_topic_id:{wo_topic_id}')
    # 获取品赞代理
    virtual_proxy_area = proxy_region
    if proxy_region in OVERSEA_REGIONS:  # 海外发送请求，默认先使用国内的'全国'请求地址，最后发送的时候改为获取海外的ip
        virtual_proxy_area = 'all'
    pz_obj = PinzanHttpProxy(virtual_proxy_area)
    pz_obj.get_proxy()
    # 创建问卷对象, 发送请求
    qo = QuestionareSpiderWjw(send_title_link=send_title_link, pz_obj=pz_obj, wo_topic_id=wo_topic_id,
                           sleep_time=sleep_time, area=proxy_region)
    res = qo.submit(submitdata)  # 提交
    # app.logger.debug(submitdata)
    return res, pz_obj.host_port_city

